package at.dcmspl;

import java.io.Serializable;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.*;

/**
 * Represents a Dicom Queue
 * @author Hannes Stornig, Gosch Daniel
 */
@Entity
@NamedQueries({
    @NamedQuery(name = DcmQueueSimple.FIND_ALL, query = "select q from DcmQueueSimple q"),
    @NamedQuery(name = DcmQueueSimple.FIND_BY_NAME, query = "select q from DcmQueueSimple q where q.name=:name")
})
public class DcmQueueSimple implements Serializable {
    private static final long serialVersionUID = 1L;
    public static final String FIND_ALL = "DcmQueueSimple.findAll";
    public static final String FIND_BY_NAME = "DcmQueueSimple.findByName";
    
    @Version
    int versionsnr;
    @Temporal(TemporalType.TIMESTAMP)
    Date angelegtAm;
    @Temporal(TemporalType.TIMESTAMP)
    Date zuletztGeaendertAm;
    
    @PrePersist public void erzeugungsattributeSetzen(){
        angelegtAm = new Date();
    }
    
    @PreUpdate public void aenderungsattributeSetzen(){
        zuletztGeaendertAm = new Date();
    }
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    @Column(unique=true)
    private String name;
     
    //FetchType Eager = EAGER bedeutet, dass das Attribut sofort geladen wird, wenn das Objekt aus der Datenbank geholt wird. 
    @OneToMany(mappedBy = "parentDcmQueue", fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true)
    private List<DcmFile> dcmFiles = new LinkedList<DcmFile>();
    
    /**
    * Constructor no-args
    * 
    */
    public DcmQueueSimple() {
    }
 
    /**
    * Constructor
    * @return DcmQueueSimple
    */
    public DcmQueueSimple(String name) {
        this.name = name;
    }   
    
    /**
    * Adds a DicomFile to the Queue with String dcmFileName
    * @param dcmFileName (Type String)
    */
    public void addDcmFile(String dcmFileName){
        //TODO Pfad definieren
        DcmFile x = new DcmFile(dcmFileName,"Pfad",this);
        dcmFiles.add(x);
        Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.INFO, "Dicom File {0} erfolgreich hinzugefügt",dcmFileName);
    }
    
    /**
    * Adds a DicomFile to the Queue
    * @param dcmFile (Type DcmFile)
    */
    public void addDcmFile(DcmFile dcmFile){
        dcmFiles.add(dcmFile);
        Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.INFO, "Dicom File {0} erfolgreich hinzugefügt",dcmFile.getName());
    }
    
    /**
    * Removes the DicomFile from the Queue
    * 
    */
    public void removeDcmFile(DcmFile dcmFile) {
        dcmFiles.remove(dcmFile);
        Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.INFO, "Dicom File {0} erfolgreich gelöscht",dcmFile.getName());
    }
    
    /**
    * Removes the Head of the Queue, Returnes the DicomFile if the File is removed
    * @return DcmFile
    */
    public DcmFile remove(){
        if(!this.isEmpty()){
            DcmFile dcmFile = dcmFiles.get(0);
            dcmFiles.remove(dcmFile);
            Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.INFO, "Kopf der Queue {0} erfolgreich gelöscht",dcmFile.getName());
            return dcmFile;
        }else{
            return null;
        }
    }
    
    /**
    * Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty
    * @return DcmFile
    */
    public DcmFile peek(){
        if(!this.isEmpty()){
            DcmFile dummy = dcmFiles.get(0);
            Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.INFO, "Peek des Dicom Files {0}",dummy.getName());
            return dummy;
        }else{
            Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.SEVERE, "Queue {0} ist leer",this.getName());
            return null;
        }
    }
    
    /**
     * Retrieves and removes the head of this queue, or returns null if this queue is empty
     * @return DcmFile
     */
    public DcmFile pool(){
        if(!dcmFiles.isEmpty()){
            DcmFile dummy = dcmFiles.get(0);
            dcmFiles.remove(0);
            Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.INFO, "Pool des Dicom Files {0}",dummy.getName());
            return dummy;
            
        }else{
            Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.SEVERE, "Queue {0} ist leer",this.getName());
            return null;
        }
    }
    
    /**
    * Retrieves the DicomObjekt Element at the specific Position of the Queue
    * @return DcmFile
    */
    public DcmFile elementAt(int Index){
        if(!dcmFiles.isEmpty() && dcmFiles.size()>=Index){
            DcmFile dummy = dcmFiles.get(Index);
            Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.INFO, "Element {0} at Position",dummy.getName());
            return dummy;
        }else{
            Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.SEVERE, "Queue {0} ist leer",this.getName());
            return null;
        }
    }
    
    /**
    * Retrieves the DicomObjekt on the specified Position and removes it form the Queue
    * TransactionAttributeType.Required
    */
    @TransactionAttribute(TransactionAttributeType.REQUIRED)//TODO Überprüfen ob so richtig
    public DcmFile movetoHead(int Index){
        if(!dcmFiles.isEmpty() && dcmFiles.size()>=Index){
            DcmFile d = dcmFiles.get(Index);
            //Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.INFO, "Zustand der Liste vor move: {0}", dcmFiles.toString());
            //Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.INFO, "Zustand der Liste nach move: {0}", dcmFiles.toString());
            this.removeDcmFile(d);
            Logger.getLogger(DcmQueueSimple.class.getName()).log(Level.INFO, "DcmFile {d} gelöscht", d.getName());
            return d;
        }else return null;
           
    }
    
    /**
    * Add a Set of DcmFiles
    * 
    */
    public void setDcmFiles(List<DcmFile> dcmFiles){
        this.dcmFiles = dcmFiles;
    }
    
    public void putDcmFile(DcmFile d){
        this.dcmFiles.add(0, d);
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }      
    
    public Long getId() {
        return id;
    }
    
    /**
    * Get Size of contained DicomFiles in the Queue
    * @return int
    */
    public int getSize(){
        return dcmFiles.size();
    }
    
    /**
    * Returns True if the Queue contains no Elements
    * @return boolean
    */
    public boolean isEmpty(){
        return dcmFiles.isEmpty();
    }

    //public void setId(Long id) {
    //    this.id = id;
    //}
    
    /**
    * Get all DicomFiles in the Queue
    * @return List<DcmFile>
    */
    public List<DcmFile> getAllDcmFiles() {
        return Collections.unmodifiableList(dcmFiles);
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof DcmQueueSimple)) {
            return false;
        }
        DcmQueueSimple other = (DcmQueueSimple) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "at.dcmspl.DcmQueueSimple[ id=" + id + " name=" + name + " ]";
    }
    
}
